﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using Eneta.Portal.Common;
using Eneta.Portal.Common.Dto;
using Eneta.Portal.Common.Helpers;
using Eneta.Portal.Common.Repository;
using FredCK.FCKeditorV2;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing;
using Microsoft.SharePoint.Utilities;

namespace Eneta.Portal.Events.Controls
{
    public class EventEditorControl : UserControl
    {
        protected Button btnSave;
        protected TextBox tbTitle;
        protected TextBox tbPlace;
        protected TextBox tbShortDesc;
        protected TextBox tbPlacesCount;
        protected DropDownList ddlTechnicalLevel;

        protected CheckBox realEventCheckBox;
        protected CheckBox virtualEventCheckBox;
        //protected DropDownList audienceList;
        protected TextBox slidesField;
        protected TextBox demosField;
        protected TextBox placeUrlField;

        protected FCKeditor descriptionField;
        protected TextBox startField;
        protected DropDownList startHourField;
        protected DropDownList startMinuteField;
        protected TextBox endField;
        protected DropDownList endHourField;
        protected DropDownList endMinuteField;
        protected TextBox registrationEndDateField;

        protected HtmlGenericControl titleContainer;
        protected HtmlGenericControl placeContainer;
        protected HtmlGenericControl startContainer;
        protected HtmlGenericControl endContainer;
        protected HtmlGenericControl shortDescContainer;
        protected HtmlGenericControl placesCountContainer;

        protected CheckBoxList targetAudiences;

        private Dictionary<string, string> errors = new Dictionary<string, string>();

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            btnSave.Click += BtnSave_Click;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            var user = SPContext.Current.Web.CurrentUser;
            if(user == null)
            {
                Response.Redirect("/");
                return;
            }
            if(!user.IsSiteAdmin)
            {
                Response.Redirect("/");
                return;
            }

            errors.Clear();

            if (!IsPostBack)
            {
                virtualEventCheckBox.InputAttributes["class"] = "choice";
                realEventCheckBox.InputAttributes["class"] = "choice";
                Bind();
            }
        }

        private void Bind()
        {
            var repository = new EventRepository(SPContext.Current.Web);
            var audiences = repository.GetAllTargetAudiences();
            targetAudiences.DataSource = audiences;
            targetAudiences.DataBind();

            using (var web = SPContext.Current.Site.OpenWeb("/sundmused/"))
            {
                var ct = web.AvailableContentTypes["Event"];
                var levelField = (SPFieldChoice) ct.Fields.GetFieldByInternalName("TechnicalLevel");

                ddlTechnicalLevel.Items.Add(string.Empty);

                foreach (var choice in levelField.Choices)
                {
                    ddlTechnicalLevel.Items.Add(choice);
                }

                //var audienceField = web.Lists["Lehed"].Fields["TargetAudience"] as SPFieldChoice;

                //audienceList.Items.Add(string.Empty);

                //foreach (var choice in audienceField.Choices)
                //{
                //    audienceList.Items.Add(choice);
                //}

            }
            if (Item == null)
            {
                //Response.Write("NULL");
                return;
            }
            tbShortDesc.Text = Item.ShortDescription;
            tbPlace.Text = Item.Location;
            tbPlacesCount.Text = Item.MaxAttendees.ToString();
            tbTitle.Text = Item.Title;
            ddlTechnicalLevel.SelectedValue = Item.TechnicalLevel;
            startField.Text = Item.StartTime.ToString("dd.MM.yyyy");            
            startHourField.SelectedValue = Item.StartTime.Hour.ToString();
            startMinuteField.Text = Item.StartTime.Minute.ToString();
            endField.Text = Item.EndTime.ToString("dd.MM.yyyy");
            endHourField.SelectedValue = Item.EndTime.Hour.ToString();
            endMinuteField.Text = Item.EndTime.Minute.ToString();

            placeUrlField.Text = Item.LocationUrl;
            realEventCheckBox.Checked = Item.HasRealEvent;
            virtualEventCheckBox.Checked = Item.HasVirtualEvent;
            demosField.Text = Item.PercentOfDemos.ToString();
            slidesField.Text = Item.PercentOfSlides.ToString();
            if (registrationEndDateField == null)
                registrationEndDateField = (TextBox) FindControl("registrationEndDateField");
            registrationEndDateField.Text = Item.RegistrationEndDate.ToString("dd.MM.yyyy");
            descriptionField.Value = Item.Description;            

            foreach (var audience in Item.Audiences)
                foreach (ListItem audienceItem in targetAudiences.Items)
                    if (audienceItem.Value == audience)
                        audienceItem.Selected = true;
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            SetCheckStyles(Controls);
        }

        protected void BtnSave_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(tbTitle.Text))
            {
                errors.Add("title", "Nimi on kohustuslik väli.");
            }

            if (string.IsNullOrEmpty(tbPlace.Text))
            {
                errors.Add("place", "Koht on kohustuslik väli.");
            }

            if (string.IsNullOrEmpty(tbShortDesc.Text))
            {
                errors.Add("shortDesc", "Lühikirjeldus on kohustuslik väli.");
            }

            int placesCount;
            if(string.IsNullOrEmpty(tbPlacesCount.Text))
            {
                errors.Add("placesCount", "Kohtade arv on kohustuslik väli.");
            }
            else if(!int.TryParse(tbPlacesCount.Text, out placesCount))
            {
                errors.Add("placesCount", "Kohtade arv ei ole korrektselt sisestatud.");
            }

            DateTime startDate, endDate, registrationEndDate;
            if(string.IsNullOrEmpty(startField.Text))
            {
                errors.Add("start", "Ürituse alguse kuupäev on kohustuslik väli.");
            }
            else if(!DateTime.TryParse(startField.Text, out startDate))
            {
                errors.Add("start", "Ürituse alguse kuupäev on valesti sisestatud.");
            }

            if (string.IsNullOrEmpty(endField.Text))
            {
                errors.Add("end", "Ürituse lõpu kuupäev on kohustuslik väli.");
            }
            else if (!DateTime.TryParse(endField.Text, out endDate))
            {
                errors.Add("end", "Ürituse lõpu kuupäev on valesti sisestatud.");
            }

            if (registrationEndDateField == null)
                registrationEndDateField = (TextBox)FindControl("registrationEndDateField");

            if (string.IsNullOrEmpty(registrationEndDateField.Text))
            {
                errors.Add("registrationEndDate", "Viimane registreerumise kuupäev on kohustuslik väli.");
            }
            else if (!DateTime.TryParse(registrationEndDateField.Text, out registrationEndDate))
            {
                errors.Add("registrationEndDate", "Viimane registreerumise kuupäev on valesti sisestatud.");
            }

            if (errors.Count > 0)
            {
                ApplyErrors();
                return;
            }

            string operation;
            try
            {
                AddApproverRoleToUser();
            }
            catch(Exception ex)
            {
                Logger.LogWarning("BtnSave_Click ERROR","");
                Logger.LogException(ex);
                return;
            }

            try
            {
                if (Item == null)
                {
                    Logger.LogInfo("SaveButtonClick(): adding new page", GetType().ToString());
                    SavePage();
                    Logger.LogInfo("SaveButtonClick(): page added", GetType().ToString());
                    operation = "evtsave";
                }
                else
                {
                    Logger.LogInfo("SaveButtonClick(): adding approver role to user", GetType().ToString());
                    UpdatePage();
                    operation = "evtedit";
                }
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
                //messageLabel.Text = "Teate salvestamine ebaõnnestus tehnilistel põhjustel";
                RemoveApproverRoleFromUser();
                return;
            }

            RemoveApproverRoleFromUser();

            var profileRepositry = new UserProfileRepository(SPContext.Current.Web);
            var profile = profileRepositry.GetUserProfileByUserName(SPContext.Current.Web.CurrentUser.LoginName);

            if (Item == null)
            {

                var currentUser = SPContext.Current.Web.CurrentUser;
                var body = "<html><body style=\"font-family:arial;font-size:10pt\">";
                body += "<p>Hei " + currentUser.Name + "!</p>";
                body += "<p>Tänud sündmuse \"" + tbTitle.Text + "\" lisamise eest Eneta portaali. ";
                body += "Sündmus ilmub peale administraatori poolset kinnitamist.</p>";

                body += "<p>Tervitustega,<br/>";
                body += "Eneta tiim</p>";
                body +=
                    "<a href=\"http://www.eneta.ee\"><img src=\"http://www.eneta.ee/SiteCollectionImages/logod/eneta_logo_250x78_sinine.png\" border=\"0\"></a>";
                body += "</body></html>";

                SPUtility.SendEmail(SPContext.Current.Web, false, false, profile.Email,
                                    "Lisasid sündmuse Eneta portaali", body);
                SPUtility.SendEmail(SPContext.Current.Web, false, false, "abi@eneta.ee", "Lisasid sündmuse Eneta portaali",
                                    body);

            }
            int userId;
            if (IsCurrentUser(out userId))
                Response.Redirect("/profile.aspx?id=" + profile.Id + "&msg=" + operation, false);
            else
                Response.Redirect("/profile.aspx?id=" + profile.Id + "&msg=" + operation, false);
        }

        private void UpdatePage()
        {
            if (!SPContext.Current.Web.CurrentUser.IsSiteAdmin)
                AddApproverRoleToUser();
            var siteId = SPContext.Current.Web.Site.ID;
            using (var site = new SPSite(siteId))
            using (var web = site.OpenWeb("/sundmused/"))
            {
                var list = web.Lists["Lehed"];
                var item = list.GetItemById(Item.Id);
                var status = item.ModerationInformation.Status;

                var dto = new AdminActivityDto();
                dto.PreviousEditor = new SPFieldUserValue(web, item["Editor"].ToString()).User.LoginName;
                dto.PreviousStatus = item.ModerationInformation.Status;
                dto.PreviousTimeStamp = (DateTime)item["Modified"];
                dto.Url = "/sundmused/" + item["FileLeafRef"];
                dto.Module = "Events";

                var pubItem = PublishingPage.GetPublishingPage(item);
                if (pubItem.ListItem.File.CheckOutStatus == SPFile.SPCheckOutStatus.None)
                    pubItem.CheckOut();
                item["Title"] = tbTitle.Text;
                item["Place"] = tbPlace.Text;
                item["PlaceOnMap"] = placeUrlField.Text;
                item["ShortDescription"] = tbShortDesc.Text;
                item["TechnicalLevel"] = ddlTechnicalLevel.Text;
                item["PlacesCount"] = tbPlacesCount.Text;
                item["PublishingPageContent"] = descriptionField.Value;
                item["HasRealEvent"] = realEventCheckBox.Checked;
                item["HasVirtualEvent"] = virtualEventCheckBox.Checked;
                //item["TargetAudience"] = audienceList.SelectedValue;
                var audienceValue = new SPFieldMultiChoiceValue();
                foreach (var audience in GetSelectedAudiences())
                    audienceValue.Add(audience);
                item["TargetAudience"] = audienceValue;

                item["PercentOfSlides"] = slidesField.Text;
                item["PercentOfDemos"] = demosField.Text;
                item["EventStartDate"] = GetDate(startField.Text, startHourField.Text, startMinuteField.Text);
                item["EventEndDate"] = GetDate(endField.Text, endHourField.Text, endMinuteField.Text);
                var regEnd = DateTime.Parse(registrationEndDateField.Text);
                if (regEnd > DateTime.MinValue)
                    item["RegistrationEndDate"] = regEnd;
                else
                    item["RegistrationEndDate"] = null;

                Logger.LogInfo("ESD: " + GetDate(startField.Text, startHourField.Text, startMinuteField.Text),"");
                Logger.LogInfo("EED: " + GetDate(endField.Text, endHourField.Text, endMinuteField.Text), "");
                Logger.LogInfo("RED: " + DateTime.Parse(registrationEndDateField.Text), "");
                item.Update();



                item.File.CheckIn("Muudetud", SPCheckinType.MajorCheckIn);

                if (status == SPModerationStatusType.Approved)
                    item.File.Approve(string.Empty);

                dto.CurrentEditor = new SPFieldUserValue(web, item["Editor"].ToString()).User.LoginName;
                dto.CurrentStatus = item.ModerationInformation.Status;
                dto.CurrentTimeStamp = (DateTime)item["Modified"];
                ActivityLogger.LogActivity(dto);
            }

            if (!SPContext.Current.Web.CurrentUser.IsSiteAdmin)
                RemoveApproverRoleFromUser();
        }


        private bool IsCurrentUser(out int userId)
        {
            string owner = Request.QueryString["Owner"];
            if (string.IsNullOrEmpty(owner))
            {
                userId = -1;
                return true;
            }
            int ownerId;
            if (!int.TryParse(owner, out ownerId))
            {
                userId = -1;
                return true;
            }
            userId = ownerId;
            return false;
        }

        private EventDto _item;
        protected EventDto Item
        {
            get
            {
                if (_item != null)
                    return _item;

                int id;
                int.TryParse(Request.QueryString["EventID"], out id);
                if (id == 0)
                    return null;

                var rep = new EventRepository(SPContext.Current.Web);
                _item = rep.GetEventById(id);
                return _item;
            }
        }

        private void ApplyErrors()
        {
            foreach (var key in errors.Keys)
            {
                var ctrl = this.FindControl(key + "Container", true) as HtmlGenericControl;
                if (ctrl != null)
                {
                    ctrl.Attributes.Add("class", "info-row failed-info");

                    ctrl = this.FindControl(key + "ErrorMessage", true) as HtmlGenericControl;
                    if (ctrl != null)
                    {
                        ctrl.Style["display"] = string.Empty;
                        ctrl = this.FindControl(key + "ErrorLabel", true) as HtmlGenericControl;
                        if (ctrl != null)
                        {
                            ctrl.InnerText = errors[key];
                        }
                    }
                }
            }
        }

        private void SavePage()
        {
            var siteId = SPContext.Current.Site.ID;

            using (var site = new SPSite(siteId))
            {
                using (var web = site.OpenWeb("/sundmused/"))
                {
                    var page = CurrentID == 0 ? CreatePage(web) : GetPage(web);
                    var item = page.ListItem;

                    item["Title"] = tbTitle.Text;
                    item["Place"] = tbPlace.Text;
                    if (!string.IsNullOrEmpty(placeUrlField.Text))
                        item["PlaceOnMap"] = new SPFieldUrlValue(placeUrlField.Text);
                    else
                        item["PlaceOnMap"] = null;

                    item["ShortDescription"] = tbShortDesc.Text;
                    item["TechnicalLevel"] = ddlTechnicalLevel.Text;
                    item["PlacesCount"] = tbPlacesCount.Text;
                    item["PublishingPageContent"] = descriptionField.Value;
                    item["HasRealEvent"] = realEventCheckBox.Checked;
                    item["HasVirtualEvent"] = virtualEventCheckBox.Checked;
                    //item["TargetAudience"] = audienceList.SelectedValue;
                    var audienceValue = new SPFieldMultiChoiceValue();
                    foreach (var audience in GetSelectedAudiences())
                        audienceValue.Add(audience);
                    item["TargetAudience"] = audienceValue;

                    item["PercentOfSlides"] = slidesField.Text;
                    item["PercentOfDemos"] = demosField.Text;
                    item["EventStartDate"] = GetDate(startField.Text, startHourField.Text, startMinuteField.Text);
                    item["EventEndDate"] = GetDate(endField.Text, endHourField.Text, endMinuteField.Text);
                    item["RegistrationEndDate"] = DateTime.Parse(registrationEndDateField.Text);

                    item.Update();
                    item.File.CheckIn(string.Empty, SPCheckinType.MajorCheckIn);
                    item.File.Update();
                }
            }

            var profileRepository = new UserProfileRepository(SPContext.Current.Web);
            var profile = profileRepository.GetUserProfileByUserName(SPContext.Current.Web.CurrentUser.LoginName);
            //Response.Redirect("/profile.aspx?ID=" + profile.Id + "&msg=annsave", false);
        }
        private DateTime GetDate(string dateString, string hourString, string minuteString)
        {
            var date = DateTime.Parse(dateString);
            var hour = int.Parse(hourString);
            var minute = int.Parse(minuteString);
            date = date.AddHours(hour);
            date = date.AddMinutes(minute);

            return date;
        }
        private PublishingPage CreatePage(SPWeb web)
        {
            var publishingWeb = PublishingWeb.GetPublishingWeb(web);

            var ct = web.AvailableContentTypes["Event"];
            // TODO: Kui ct on null

            var layouts = publishingWeb.GetAvailablePageLayouts(ct.Id);
            var newsLayout = layouts[0];
            var list = web.Lists["Lehed"];
            var pages = publishingWeb.GetPublishingPages();

            var pageName = UrlHelper.GetPageFileName(tbTitle.Text);
            var pageUrl = list.RootFolder.ServerRelativeUrl + "/" + pageName;
            var counter = 1;

        checkpage:
            var page = web.GetFile(pageUrl);
            if (page != null)
                if (page.Exists)
                {
                    if (counter == 1)
                        pageUrl = pageUrl.Replace(".aspx", "-1.aspx");
                    else
                        pageUrl = pageUrl.Replace("-" + (counter - 1) + ".aspx", "-" + counter + ".aspx");
                    counter++;
                    goto checkpage;
                }

            var publishingPage = pages.Add(pageUrl, newsLayout);
            var item = publishingPage.ListItem;
            item["ContentTypeId"] = ct.Id;
            item["Title"] = tbTitle.Text;
            item.Update();
            publishingPage.Update();

            return publishingPage;
        }

        private int _currentID;
        private int CurrentID
        {
            get
            {
                if (_currentID != 0)
                    return 0;

                int.TryParse(Request.QueryString["EventID"] ?? string.Empty, out _currentID);
                return _currentID;
            }
        }

        private PublishingPage GetPage(SPWeb web)
        {
            var list = web.Lists["Lehed"];
            var item = list.GetItemById(CurrentID);

            return PublishingPage.GetPublishingPage(item);
        }

        private void AddApproverRoleToUser()
        {
            var userId = SPContext.Current.Web.CurrentUser.LoginName;
            var siteId = SPContext.Current.Site.ID;
            SPSecurity.RunWithElevatedPrivileges(delegate
            {
                using (var pubsite = new SPSite(siteId))
                using (var pubweb = pubsite.OpenWeb("/sundmused/"))
                {
                    pubweb.AllowUnsafeUpdates = true;
                    var pubList = pubweb.Lists["Lehed"];

                    var cuser = pubweb.SiteUsers[userId];

                    var assq = from a in pubList.RoleAssignments.Cast<SPRoleAssignment>()
                               from r in a.RoleDefinitionBindings.Cast<SPRoleDefinition>()
                               where a.Member.Name == cuser.LoginName &&
                                     r.Name == "Kinnitamine"
                               select a;

                    if (assq.Count() == 0)
                    {
                        Logger.LogInfo("SaveButtonClick(): assq is 0", GetType().ToString());
                        var ass2 = new SPRoleAssignment(cuser);
                        var rb2 = pubweb.RoleDefinitions["Kinnitamine"];
                        ass2.RoleDefinitionBindings.Add(rb2);
                        pubList.RoleAssignments.Add(ass2);
                        pubList.Update();
                    }
                    pubweb.AllowUnsafeUpdates = false;

                }
            });
        }

        private void RemoveApproverRoleFromUser()
        {
            var userId2 = SPContext.Current.Web.CurrentUser.LoginName;
            var siteId = SPContext.Current.Site.ID;
            SPSecurity.RunWithElevatedPrivileges(delegate
            {
                using (var pubsite = new SPSite(siteId))
                using (var pubweb = pubsite.OpenWeb("/sundmused/"))
                {
                    pubweb.AllowUnsafeUpdates = true;
                    var pubList = pubweb.Lists["Lehed"];

                    var cuser = pubweb.SiteUsers[userId2];

                    //var ass = pubList.RoleAssignments.GetAssignmentByPrincipal(cuser);
                    pubList.RoleAssignments.Remove(cuser);
                    pubList.Update();
                    pubweb.AllowUnsafeUpdates = false;
                }
            });
        }

        private static void SetCheckStyles(ControlCollection controls)
        {
            foreach (Control c in controls)
                if (c.GetType() == typeof(CheckBox))
                    ((CheckBox)c).InputAttributes["class"] = "choice";
                else if (c.HasControls())
                    SetCheckStyles(c.Controls);

        }

        private List<string> GetSelectedAudiences()
        {
            var list = new List<string>();
            foreach (ListItem item in targetAudiences.Items)
                if (item.Selected)
                    list.Add(item.Text);

            return list;
        }
    }
}
